﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xrm.Sdk.Workflow;
using System.Activities;
using Microsoft.Xrm.Sdk;
using Microsoft.Crm.Sdk.Messages;
using Microsoft.Crm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using System.Xml.Serialization;
using System.IO;
using System.Runtime.Serialization;
using System.Xml;
using System.Threading;

/**
 * Copyright 2011 by Alberto Gemin
 * agemin@hotmail.com
 * Version 1.7.0.1
 * 13 Dec 2011
 **/
namespace Gemina.CRM2011.WF.LdgManager
{
    [AgCodeActivity(ActivityNameInstantiateFilter, AgViewsUtils.GroupName)]
    public class AgInstantiateFilter : AgCodeActivityBase
    {

        #region Constants

        private const string ActivityNameInstantiateFilter = "Instantiate Filter";
        private const string Param1InputViewId = "Filter Template Id";
        private const string Param2InputSavedQuery = "Filter Template";
        private const string Param3InputUser = "Target User";
        private const string MsgBothNotNull = "{0} and {1} cannot be both populated.";
        private const string MsgBothNull = "{0} and {1} cannot be both null.";
        private const string MsgInvalidSavedView = "Invalid system view for this operation.";
        private const string MsgInvalidTemplate = "Operation invalid for query type {0}. Setting default template is only valid for query types {1} and {2}.";
        private const string MsgNull = "{0} cannot be both null.";

        #endregion

        #region Properties

        public string ValidatedViewId { get; set; }

        #endregion

        #region Workflow Input Parameters

        /// <summary>
        /// Input parameter
        /// </summary>
        [Input(Param1InputViewId)]
        public InArgument<String> InputViewId { get; set; }

        /// <summary>
        /// Input parameter
        /// </summary>
        [Input(Param2InputSavedQuery)]
        [ReferenceTarget(AgViewsUtils.EntityNameSavedQuery)]
        public InArgument<EntityReference> InputSavedQuery { get; set; }

        /// <summary>
        /// Input parameter
        /// </summary>
        [Input(Param3InputUser)]
        [ReferenceTarget(AgViewsUtils.EntityNameSystemUser)]
        [RequiredArgument]
        public InArgument<EntityReference> InputUser { get; set; }

        #endregion

        #region Properties

        public EntityReference ValidatedUser { get; set; }

        #endregion

        #region CodeActivity

        override protected bool ExecuteBody(CodeActivityContext executionContext)
        {
            Guid queryId = this.CheckArguments(executionContext);
            Entity currentQuery = this.RetrieveEntity(executionContext, queryId);

            EntityReferenceCollection templates = new EntityReferenceCollection();
            templates.Add(new EntityReference(
                currentQuery.LogicalName,
                currentQuery.Id));

            InstantiateFiltersRequest request = new InstantiateFiltersRequest
            {
                UserId = this.ValidatedUser.Id,
                TemplateCollection = templates
            };
            InstantiateFiltersResponse response = (InstantiateFiltersResponse)this.GetService(executionContext).Execute(request);
            return true;
        }

        #endregion

        #region Local Methods

        private Guid CheckArguments(CodeActivityContext executionContext)
        {
            this.ValidatedViewId = this.InputViewId.Get(executionContext);
            EntityReference validatedSavedQuery = this.InputSavedQuery.Get(executionContext);
            bool validatedIsSavedQuery = (validatedSavedQuery != null);
            this.ValidatedUser = this.InputUser.Get(executionContext);

            if (this.ValidatedUser==null)
            {
                throw new AgErrorMessage(string.Format(MsgNull , Param3InputUser ));
            }

            if (!string.IsNullOrEmpty(this.ValidatedViewId))
            {
                if (validatedIsSavedQuery)
                {
                    throw new AgErrorMessage(string.Format(MsgBothNotNull, Param1InputViewId, Param2InputSavedQuery));
                }
                return new Guid(this.ValidatedViewId);
            }
            else
            {
                if (!validatedIsSavedQuery)
                {
                    throw new AgErrorMessage(string.Format(MsgBothNull, Param1InputViewId, Param2InputSavedQuery));
                }
                return validatedSavedQuery.Id;
            }
        }

        private Entity RetrieveEntity(CodeActivityContext executionContext, Guid queryId)
        {
            Entity currentQuery = this.GetService(executionContext).Retrieve(AgViewsUtils.EntityNameSavedQuery, queryId,
                new ColumnSet(AgViewsUtils.FieldQueryType));

            if (!currentQuery.Attributes.Contains(AgViewsUtils.FieldQueryType))
            {
                throw new AgErrorMessage(MsgInvalidSavedView);
            }
            SavedQueryQueryTypeEnum queryType = (SavedQueryQueryTypeEnum)currentQuery.Attributes[AgViewsUtils.FieldQueryType];
            if (queryType != SavedQueryQueryTypeEnum.OfflineTemplate && queryType != SavedQueryQueryTypeEnum.OutlookTemplate)
            {
                throw new AgErrorMessage(string.Format(MsgInvalidTemplate, queryType, SavedQueryQueryTypeEnum.OfflineTemplate, SavedQueryQueryTypeEnum.OutlookTemplate));
            }

            return currentQuery;
        }

        #endregion

    }
}
